<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue PDF 单页阅读器</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
      min-height: 100vh;
      padding: 20px;
      color: #333;
    }
    .container {
      max-width: 1000px;
      margin: 0 auto;
      background-color: white;
      border-radius: 12px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
      overflow: hidden;
    }
    header {
      background: linear-gradient(90deg, #4b6cb7 0%, #182848 100%);
      color: white;
      padding: 20px;
      text-align: center;
    }
    h1 {
      font-size: 28px;
      margin-bottom: 10px;
    }
    .subtitle {
      font-size: 16px;
      opacity: 0.8;
    }
    .main-content {
      padding: 25px;
    }
    .upload-section {
      border: 2px dashed #4b6cb7;
      border-radius: 8px;
      padding: 30px;
      text-align: center;
      margin-bottom: 25px;
      transition: all 0.3s;
      background-color: #f8fafc;
    }
    .upload-section:hover {
      background-color: #edf2f7;
    }
    .upload-btn {
      display: inline-block;
      background: #4b6cb7;
      color: white;
      padding: 12px 25px;
      border-radius: 6px;
      cursor: pointer;
      font-weight: 600;
      transition: background 0.3s;
      margin-top: 15px;
    }
    .upload-btn:hover {
      background: #3a5795;
    }
    .file-name {
      margin-top: 15px;
      font-style: italic;
      color: #4a5568;
    }
    .controls {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20px;
      flex-wrap: wrap;
      gap: 15px;
    }
    .page-controls {
      display: flex;
      align-items: center;
      gap: 10px;
    }
    .page-input {
      width: 70px;
      padding: 8px 12px;
      border: 1px solid #cbd5e0;
      border-radius: 4px;
      text-align: center;
    }
    .nav-btn {
      background: #4b6cb7;
      color: white;
      border: none;
      padding: 8px 15px;
      border-radius: 4px;
      cursor: pointer;
      transition: background 0.3s;
    }
    .nav-btn:hover:not(:disabled) {
      background: #3a5795;
    }
    .nav-btn:disabled {
      background: #a0aec0;
      cursor: not-allowed;
    }
    .pdf-container {
      border: 1px solid #e2e8f0;
      border-radius: 8px;
      overflow: auto;
      background-color: #f7fafc;
      min-height: 500px;
      display: flex;
      justify-content: center;
      align-items: flex-start;
      padding: 20px;
    }
    .canvas-container {
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      border-radius: 4px;
      overflow: hidden;
    }
    .status {
      text-align: center;
      padding: 20px;
      color: #4a5568;
    }
    .error {
      color: #e53e3e;
      text-align: center;
      padding: 15px;
      background-color: #fed7d7;
      border-radius: 6px;
      margin-top: 15px;
    }
    footer {
      text-align: center;
      padding: 15px;
      color: #718096;
      font-size: 14px;
      border-top: 1px solid #e2e8f0;
    }
    @media (max-width: 768px) {
      .controls {
        flex-direction: column;
        align-items: stretch;
      }
      .page-controls {
        justify-content: center;
      }
    }
  </style>
</head>
<body>
  <div id="app">
    <div class="container">
      <header>
        <h1>Vue PDF 单页阅读器</h1>
        <p class="subtitle">上传PDF文件并浏览指定页面</p>
      </header>
      
      <div class="main-content">
        <div class="upload-section">
          <p>请选择要浏览的PDF文件</p>
          <input 
            type="file" 
            id="fileInput" 
            @change="handleFileUpload" 
            accept=".pdf" 
            style="display: none"
          >
          <label for="fileInput" class="upload-btn">选择PDF文件</label>
          <div v-if="fileName" class="file-name">已选择: {{ fileName }}</div>
        </div>
        
        <div v-if="pdfLoaded" class="controls">
          <div class="page-controls">
            <button class="nav-btn" @click="prevPage" :disabled="currentPage <= 1">上一页</button>
            <span>第</span>
            <input 
              type="number" 
              v-model.number="currentPage" 
              @change="goToPage" 
              class="page-input" 
              min="1" 
              :max="totalPages"
            >
            <span>页，共 {{ totalPages }} 页</span>
            <button class="nav-btn" @click="nextPage" :disabled="currentPage >= totalPages">下一页</button>
          </div>
          <div>
            <button class="nav-btn" @click="zoomOut" :disabled="scale <= 0.5">缩小</button>
            <span>缩放: {{ Math.round(scale * 100) }}%</span>
            <button class="nav-btn" @click="zoomIn" :disabled="scale >= 2">放大</button>
          </div>
        </div>
        
        <div class="pdf-container">
          <div v-if="!pdfLoaded && !error" class="status">
            <p>请上传PDF文件开始浏览</p>
          </div>
          <div v-else-if="error" class="error">
            {{ error }}
          </div>
          <div v-else class="canvas-container">
            <canvas ref="pdfCanvas"></canvas>
          </div>
        </div>
      </div>
      
      <footer>
        <p>基于 Vue.js 和 PDF.js 构建</p>
      </footer>
    </div>
  </div>

  <script>
    // 设置PDF.js worker路径
    pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js';
    
    new Vue({
      el: '#app',
      data: {
        pdfDoc: null,
        currentPage: 1,
        totalPages: 0,
        scale: 1.2,
        fileName: '',
        error: '',
        pdfLoaded: false
      },
      methods: {
        handleFileUpload(event) {
          const file = event.target.files[0];
          if (!file) return;
          
          this.fileName = file.name;
          this.error = '';
          
          if (file.type !== 'application/pdf') {
            this.error = '请选择PDF文件';
            return;
          }
          
          const fileReader = new FileReader();
          
          fileReader.onload = () => {
            const typedArray = new Uint8Array(fileReader.result);
            
            // 加载PDF文档
            pdfjsLib.getDocument(typedArray).promise.then(pdf => {
              this.pdfDoc = pdf;
              this.totalPages = pdf.numPages;
              this.currentPage = 1;
              this.pdfLoaded = true;
              this.renderPage(this.currentPage);
            }).catch(error => {
              this.error = 'PDF加载失败: ' + error.message;
              this.pdfLoaded = false;
            });
          };
          
          fileReader.readAsArrayBuffer(file);
        },
        
        renderPage(pageNum) {
          if (!this.pdfDoc) return;
          
          this.pdfDoc.getPage(pageNum).then(page => {
            const canvas = this.$refs.pdfCanvas;
            const ctx = canvas.getContext('2d');
            
            const viewport = page.getViewport({ scale: this.scale });
            canvas.height = viewport.height;
            canvas.width = viewport.width;
            
            const renderContext = {
              canvasContext: ctx,
              viewport: viewport
            };
            
            page.render(renderContext).promise.then(() => {
              console.log(`第 ${pageNum} 页渲染完成`);
            });
          }).catch(error => {
            this.error = '页面渲染失败: ' + error.message;
          });
        },
        
        prevPage() {
          if (this.currentPage > 1) {
            this.currentPage--;
            this.renderPage(this.currentPage);
          }
        },
        
        nextPage() {
          if (this.currentPage < this.totalPages) {
            this.currentPage++;
            this.renderPage(this.currentPage);
          }
        },
        
        goToPage() {
          if (this.currentPage < 1) this.currentPage = 1;
          if (this.currentPage > this.totalPages) this.currentPage = this.totalPages;
          this.renderPage(this.currentPage);
        },
        
        zoomIn() {
          if (this.scale < 2) {
            this.scale += 0.1;
            this.renderPage(this.currentPage);
          }
        },
        
        zoomOut() {
          if (this.scale > 0.5) {
            this.scale -= 0.1;
            this.renderPage(this.currentPage);
          }
        }
      }
    });
  </script>
</body>
</html>